AddCSLuaFile( "cl_init.lua" ) -- Make sure clientside  
AddCSLuaFile( "shared.lua" )  --and shared scripts are sent.     
include('shared.lua')     

function ENT:SpawnFunction( ply, tr )
	if ( not tr.Hit ) then return end
	local SpawnPos = tr.HitPos + tr.HitNormal * 16 + Vector(0,0,30)
	local ent = ents.Create("sent_spaceanon_spore");
	ent:SetPos(SpawnPos);
	ent:Spawn();
	ent:Activate();
	return ent
end

function ENT:Initialize()   
	//self.Entity:SetModel("models/LS/spore.mdl")--NewModel
	self.Entity:SetModel("models/Weapons/w_bugbait.mdl")--Old working model
	self.Entity:PhysicsInit(SOLID_VPHYSICS)
	self.Entity:SetMoveType(MOVETYPE_VPHYSICS)
	self.Entity:SetSolid(SOLID_VPHYSICS)
	self.Entity:NextThink(CurTime()+1)
	self.Entity:SetMaterial("models/debug/debugwhite")
	
	if self.Entity:GetPhysicsObject():IsValid() then
		self.Entity:GetPhysicsObject():Wake()
	//	self.Entity:EnableGravity( false )
	//	self.Entity:EnableDrag( false )	
	end
	
	if table.Count(ents.FindByClass("sent_spaceanon_spore")) >= self.maxspores then
		self:SetParent(nil)
		self.Entity:Remove()
	end
	
	self.PhysObj = self.Entity:GetPhysicsObject()
	self.CAng = self.Entity:GetAngles()
end

function ENT:OnTakeDamage(dmg)
	local chance = math.random(1,40) --Was 20 made chance lower
	if dmg:IsExplosionDamage() and chance == 1 then return end --changed to give a chance for a chain reaction.
	if dmg:GetAttacker():GetClass() ~= "sent_spaceanon_spore" then
		if dmg:GetDamage() > 25 then
			local pos = self.Entity:GetPos()
			local effectdata = EffectData()
				effectdata:SetOrigin( pos )
				effectdata:SetStart(self.Entity:GetPos())
				effectdata:SetMagnitude( 80 )
				effectdata:SetScale( 10 )
				effectdata:SetRadius( 30 )
			util.Effect( "Explosion", effectdata )
			self:Explode(pos)
			self:SetParent(nil)
			self.Entity:Remove()
		end
	end
end

function ENT:Explode(pos)
	util.BlastDamage(GetWorldEntity(), GetWorldEntity(), pos, 500, (60+math.random(5,20)))
end

function ENT:Touch(activator)
	if activator:GetClass() ~= "sent_spaceanon_spore" then
		local pos = self.Entity:GetPos()
		if activator:GetClass() == "player" or string.find(activator:GetClass(), "npc_") or ((activator:GetVelocity()+self.Entity:GetVelocity()):Length() > 1500) then
			local effectdata = EffectData()
			effectdata:SetOrigin(pos)
			effectdata:SetStart(self.Entity:GetPos())
			effectdata:SetMagnitude(80)
			effectdata:SetScale(10)
			effectdata:SetRadius(30)
			util.Effect( "Explosion", effectdata )
			timer.Simple(.2, self.Explode, self, pos) --hack
			self:SetParent(nil)
			self:Remove()
		else
			if not self.weld then
				if not self.latched then
				//	print("Now latched")
					self.Entity:SetParent(activator)
					self.latched = true
				end
			else
				constraint.Weld(self.Entity, activator, 0, 0, 0, true)
			end
		end
	else
		if not self.latched then
			self:SetParent(nil)
			self.Entity:Remove()-- Removed your clusterfuck orgys you sick bastards!!!!
		end
	end
end

 function ZoneCheck(Pos,Size)  
        local XB, YB, ZB = Size * 0.5, Size * 0.5, Size * 0.5
        local Results = {}
        local Clear = true
        for k,e in pairs(ents.FindByClass("sent_spaceanon_spore")) do --Need to rework this some day
            local EP = e:GetPos()
                   
            local EPL = WorldToLocal( EP, Angle(0,0,0), Pos, Angle(0,0,0))
            local X,Y,Z = EPL.x, EPL.y, EPL.z
                   
            if X <= XB and X >= -XB and Y <= YB and Y >= -YB and Z <= ZB and Z >= -ZB then
                Clear = false
            end
        end
    return Clear
end

function ENT:Reproduce()--If its too laggy ill optomise
//	print("Reproducing")
	local n = math.Rand(0,360)
	local d = math.Rand(10,100)
	local trace = {}
	trace.start = self:GetPos()
	trace.endpos = self:GetPos() + (self:GetForward() * 40) + (self:GetRight() * (math.cos(n) * d)) + (self:GetUp() * (math.sin(n) * d))
	trace.filter = self
	local tr = util.TraceLine( trace )
    if tr.Hit then
        if !tr.HitWorld and tr.Entity:GetClass() ~= "sent_spaceanon_spore" and tr.Entity:GetClass() ~= "player" then return end
		if !ZoneCheck(tr.HitPos,100) then return end
	//	print("First trace is success!")
            self:Generate(tr.HitPos,tr.HitNormal,tr.Entity)
        else
			//print("First trace failed")
            local d2 = math.Rand(10,100) + d
            local trace2 = {}
            trace2.start = tr.HitPos
            trace2.endpos = self:GetPos() + (self:GetForward() * -20) + (self:GetRight() * (math.cos(n) * d2)) + (self:GetUp() * (math.sin(n) * d2))
            trace2.filter = self
            local tr2 = util.TraceLine( trace2 )
            if tr2.Hit then
            if !tr2.HitWorld and !tr2.Entity:GetClass() == "sent_spaceanon_spore" and tr.Entity:GetClass() ~= "player" then return end
            if !ZoneCheck(tr2.HitPos,100) then return end
            self:Generate(tr2.HitPos,tr2.HitNormal,tr2.Entity)
        end
    end
end

function ENT:Generate(Pos,Norm,HEnt)
    local P1 = Pos + Norm
    local P2 = Pos - Norm
    local ent = ents.Create( "sent_spaceanon_spore" )
    local RA = Norm:Angle()
    RA:RotateAroundAxis(Norm,math.Rand(0,360))
    ent:SetAngles(RA)
    ent:SetPos( Pos + Norm * 2 )
    ent:Spawn()
    ent:Initialize()
    ent:Activate()
	ent.latched=1
	ent.Baby=true
    ent.weld=true
	constraint.Weld(self.Entity, activator, 0, 0, 0, true)
    if !HEnt:IsWorld() then
        ent:SetParent(HEnt)
    end
end

function ENT:Use( activator, caller ) -- Was a test
	self:SetParent(nil)
	self.Entity:Remove()-- OM NOM NOM NOM
end

function ENT:Follow()
	local phy = self.Entity:GetPhysicsObject()
	if self.Target and self.Target:IsValid() then
		--if self.Target and self.Target:IsValid() then
		local IMass = self.Target:GetPhysicsObject():GetMass()
		local IDist = (self.Entity:GetPos() - self.Target:GetPos()):Length()
		local TVal = (IMass * 3) - IDist				
		if !self.Entity:GetTracking() then self.Entity:SetTracking( true ) end
			local DVec = self.Target:GetPos() - self.Entity:GetPos()
			phy:SetVelocity( (DVec:Normalize() * ((self.Target:GetPhysicsObject():GetVelocity():Length() * 0.1) + (TVal * 0.01) )) + phy:GetVelocity() )
			--phy:ApplyForceCenter( DVec:Normalize() * ((self.Target:GetPhysicsObject():GetVelocity():Length() * 100) + (TVal * 2000 ) )
			if TVal <= 0 then
				self.Target = nil
			end
		else
			if self.Entity:GetTracking() then self.Entity:SetTracking( false ) end
				local targets = ents.FindInSphere( self.Entity:GetPos(), 5000)
				local CMass = 0
				local CT = nil
				for _,i in pairs(targets) do
					if i:GetPhysicsObject() and i:GetPhysicsObject():IsValid() and !i.SporeProof and !i:IsPlayer() then
						local IMass = i:GetPhysicsObject():GetMass()
						local IDist = (self.Entity:GetPos() - i:GetPos()):Length()
						local TVal = (IMass * 3) - IDist
						if TVal > CMass then
							CT = i
						end
					end
				end
		self.Target = CT
		phy:SetVelocity( phy:GetVelocity() * 0.9 )
	end
end

function ENT:Think()
	local X=self.CX	
	local Y=self.CY
	local Z=self.CZ	
	local A=self.CA	
	self.Entity:SetColor(X,Y,Z,A)	
	if self.latched then
		if self.Stype==0 then
			if math.random(1,20)==3 then
			//print("Spore is a spreader and latched")
				self:Reproduce() --Moved here for testing
			end
		elseif self.Stype==1 then
			if math.random(1,30)==15 then
				self:Reproduce()
			end
		elseif self.Stype==2 then
			local boom = math.random(1,80)
			if boom==1 then
			//	print("BOOM!!!")
				self:SetParent(nil)
				local pos = self.Entity:GetPos()
				local effectdata = EffectData()
				effectdata:SetOrigin(pos)
				effectdata:SetStart(self.Entity:GetPos())
				effectdata:SetMagnitude(80)
				effectdata:SetScale(10)
				effectdata:SetRadius(30)
				util.Effect( "Explosion", effectdata )
				timer.Simple(.2, self.Explode, self, pos) --hack
				self:Remove()
			end
		end
	else
		if self.Stype==1 then
			self:Follow()
		end
	end
	self.Entity:NextThink(CurTime()+1)
end
